home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / iface.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  13KB  |  557 lines

  1. /*
  2.     IP interface control and configuration routines
  3.      Copyright 1991 Phil Karn, KA9Q
  4. */
  5.  
  6. /****************************************************************************
  7. *    $Id: iface.c 1.3 93/07/16 11:45:31 ROOT_DOS Exp $
  8. *    04 Jul 93    1.2        GT    Fix warnings.                                    *
  9.  
  10.     Atari version by David Nash - dnash@chaos.demon.co.uk
  11.  
  12.     11.06.94 - add ifconfig up/down
  13.     
  14. ****************************************************************************/
  15.  
  16. #include <stdio.h>
  17. #include <ctype.h>
  18. #include "config.h"
  19. #include "pc.h"
  20. #include "global.h"
  21. #include "mbuf.h"
  22. #include "proc.h"
  23. #include "iface.h"
  24. #include "ip.h"
  25. #include "netuser.h"
  26. #include "ax25.h"
  27. #include "enet.h"
  28. #include "pktdrvr.h"
  29. #include "cmdparse.h"
  30. #include "commands.h"
  31. #include "devparam.h"
  32.  
  33. static void showiface __ARGS((struct iface *ifp));
  34. static int mask2width __ARGS((int32 mask));
  35. static int ifipaddr __ARGS((int argc,char *argv[],void *p));
  36. static int iflinkadr __ARGS((int argc,char *argv[],void *p));
  37. static int ifbroad __ARGS((int argc,char *argv[],void *p));
  38. static int ifnetmsk __ARGS((int argc,char *argv[],void *p));
  39. static int ifrxbuf __ARGS((int argc,char *argv[],void *p));
  40. static int ifmtu __ARGS((int argc,char *argv[],void *p));
  41. static int ifforw __ARGS((int argc,char *argv[],void *p));
  42. static int ifencap __ARGS((int argc,char *argv[],void *p));
  43.  
  44. /* Interface list header */
  45. struct iface *Ifaces = &Loopback;
  46.  
  47. /* Loopback pseudo-interface */
  48. struct iface Loopback = {
  49.     &Encap,                                                /* Link to next entry             */
  50.     "loopback",                                            /* name                                */
  51.     0x7f000001L,                                        /* addr         127.0.0.1             */
  52.     0xffffffffL,                                        /* broadcast 255.255.255.255    */
  53.     0xffffffffL,                                        /* netmask     255.255.255.255     */
  54.     MAXINT16,                                            /* mtu         No limit             */
  55.     0,                                                        /* flags                                */
  56.     0,                                                        /* trace                                */
  57.     NULLCHAR,                                            /* trfile                            */
  58.     NULLFILE,                                            /* trfp                                */
  59.     NULLIF,                                                /* forw                                */
  60.     NULLPROC,                                            /* rxproc                            */
  61.     NULLPROC,                                            /* txproc                            */
  62.     NULLPROC,                                            /* supv                                */
  63. #ifdef FILTER
  64.     NULL,                                                    /* infilter                            */
  65.     NULL,                                                    /* outfilter                        */
  66. #endif
  67.     0,                                                        /* dev                                */
  68.     NULL,                                                    /* (*ioctl)                            */
  69.     NULLFP,                                                /* (*iostatus)                        */
  70.     NULLFP,                                                /* (*stop)                            */
  71.     NULLCHAR,                                            /* hwaddr                            */
  72.     NULL,                                                    /* extension                        */
  73.     CL_NONE,                                                /* type                                */
  74.     0,                                                        /* xdev                                */
  75.     &Iftypes[0],                                        /* iftype                            */
  76.     NULLFP,                                                /* (*send)                            */
  77.     NULLFP,                                                /* (*output)                        */
  78.     NULLFP,                                                /* (*raw)                            */
  79.     NULLVFP,                                                /* (*status)                        */
  80.     NULLFP,                                                /* (*discard)                        */
  81.     NULLFP,                                                /* (*echo)                            */
  82.     0,                                                        /* ipsndcnt                            */
  83.     0,                                                        /* rawsndcnt                        */
  84.     0,                                                        /* iprecvcnt                        */
  85.     0,                                                        /* rawrcvcnt                        */
  86.     0,                                                        /* lastsent                            */
  87.     0,                                                        /* lastrecv                            */
  88. };
  89.  
  90. /* Encapsulation pseudo-interface */
  91.  
  92. struct iface Encap = {
  93.     NULLIF,
  94.     "encap",                                                /* name                                */
  95.     INADDR_ANY,                                            /* addr         0.0.0.0             */
  96.     0xffffffffL,                                        /* broadcast 255.255.255.255     */
  97.     0xffffffffL,                                        /* netmask     255.255.255.255     */
  98.     MAXINT16,                                            /* mtu         No limit             */
  99.     0,                                                        /* flags                                */
  100.     0,                                                        /* trace                                */
  101.     NULLCHAR,                                            /* trfile                            */
  102.     NULLFILE,                                            /* trfp                                */
  103.     NULLIF,                                                /* forw                                */
  104.     NULLPROC,                                            /* rxproc                            */
  105.     NULLPROC,                                            /* txproc                            */
  106.     NULLPROC,                                            /* supv                                */
  107. #ifdef FILTER
  108.     NULL,                                                    /* infilter                            */
  109.     NULL,                                                    /* outfilter                        */
  110. #endif
  111.     0,                                                        /* dev                                */
  112.     NULL,                                                    /* (*ioctl)                            */
  113.     NULLFP,                                                /* (*iostatus)                        */
  114.     NULLFP,                                                /* (*stop)                            */
  115.     NULLCHAR,                                            /* hwaddr                            */
  116.     NULL,                                                    /* extension                        */
  117.     CL_NONE,                                                /* type                                */
  118.     0,                                                        /* xdev                                */
  119.     &Iftypes[0],                                        /* iftype                            */
  120.     ip_encap,                                            /* (*send)                            */
  121.     NULLFP,                                                /* (*output)                        */
  122.     NULLFP,                                                /* (*raw)                            */    
  123.     NULLVFP,                                                /* (*status)                        */
  124.     NULLFP,                                                /* (*discard)                        */
  125.     NULLFP,                                                /* (*echo)                            */
  126.     0,                                                        /* ipsndcnt                            */
  127.     0,                                                        /* rawsndcnt                        */
  128.     0,                                                        /* iprecvcnt                        */
  129.     0,                                                        /* rawrcvcnt                        */
  130.     0,                                                        /* lastsent                            */
  131.     0,                                                        /* lastrecv                            */
  132. };
  133.  
  134. char Noipaddr[] = "IP address field missing, and ip address not set\n";
  135.  
  136. struct cmds Ifcmds[] = {
  137.     { "broadcast",            ifbroad,        0,    2,    NULLCHAR },
  138.     { "encapsulation",    ifencap,        0,    2,    NULLCHAR },
  139.     { "forward",            ifforw,        0,    2,    NULLCHAR },
  140.     { "ipaddress",            ifipaddr,    0,    2,    NULLCHAR },
  141.     { "linkaddress",        iflinkadr,    0,    2,    NULLCHAR },
  142.     { "mtu",                    ifmtu,        0,    2,    NULLCHAR },
  143.     { "netmask",            ifnetmsk,    0,    2,    NULLCHAR },
  144.     { "rxbuf",                ifrxbuf,        0,    2,    NULLCHAR },
  145.     { NULLCHAR },
  146. };
  147.  
  148.  
  149. /*
  150.     doifconfig - Set interface parameters
  151. */
  152.  
  153. int doifconfig(int argc, char *argv[], void *p)
  154. {
  155.     int i;
  156.     struct iface *ifp;
  157.  
  158.     if (argc < 2) {
  159.         for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  160.             showiface(ifp);
  161.         return 0;
  162.     }
  163.     
  164.     if ((ifp = if_lookup(argv[1])) == NULLIF) {
  165.         tprintf("Interface %s unknown\n", argv[1]);
  166.         return 1;
  167.     }
  168.     
  169.     if (argc == 2) {
  170.         showiface(ifp);
  171.         if (ifp->show != 0 ) {
  172.             (*ifp->show)(ifp);
  173.         }
  174.         return 0;
  175.     }
  176.     
  177.     if (argc == 3) {
  178.         if (tolower(*argv[2]) == 'u' && ifp->iostatus != 0) {
  179.             (*ifp->iostatus)(ifp, PARAM_UP, 0);
  180.             return 0;
  181.         }
  182.  
  183.         if (tolower(*argv[2]) == 'd' && ifp->iostatus != 0) {
  184.             (*ifp->iostatus)(ifp, PARAM_DOWN, 0);
  185.             return 0;
  186.         }
  187.  
  188.         tprintf("Argument missing\n");
  189.         return 1;
  190.     }
  191.     
  192.     for (i = 2; i < argc-1; i += 2)
  193.         subcmd(Ifcmds, 3, &argv[i-1], ifp);
  194.  
  195.     return 0;
  196. }
  197.  
  198.  
  199. /*
  200.     ifipaddr - Set interface IP address
  201. */
  202.  
  203. static int ifipaddr(int argc, char *argv[], void *p)
  204. {
  205.     struct iface *ifp = p;
  206.  
  207.     ifp->addr = resolve(argv[1]);
  208.     return 0;
  209. }
  210.  
  211.  
  212. /*
  213.     iflinkadr - Set link (hardware) address
  214. */
  215.  
  216. static int iflinkadr(int argc, char *argv[], void *p)
  217. {
  218.     struct iface *ifp = p;
  219.  
  220.     if (ifp->iftype == NULLIFT || ifp->iftype->scan == NULL) {
  221.         tprintf("Can't set link address\n");
  222.         return 1;
  223.     }
  224.     
  225.     if (ifp->hwaddr != NULLCHAR)
  226.         free(ifp->hwaddr);
  227.     ifp->hwaddr = mallocw(ifp->iftype->hwalen);
  228.     (*ifp->iftype->scan)(ifp->hwaddr, argv[1]);
  229.     return 0;
  230. }
  231.  
  232.  
  233. /*
  234.     ifbroad - Set interface broadcast address. This is actually done
  235.              by installing a private entry in the routing table.
  236. */
  237.  
  238. static int ifbroad(int argc, char *argv[], void *p)
  239. {
  240.     struct iface *ifp = p;
  241.     struct route *rp;
  242.  
  243.     rp = rt_blookup(ifp->broadcast,32);
  244.  
  245.     if (rp != NULLROUTE && rp->iface == ifp)
  246.         rt_drop(ifp->broadcast,32);
  247.     ifp->broadcast = resolve(argv[1]);
  248.     rt_add(ifp->broadcast, 32, 0L, ifp, 1L, 0L, 1);
  249.     return 0;
  250. }
  251.  
  252.  
  253. /*
  254.     ifnetmsj - Set the network mask. This is actually done by installing
  255.               a routing entry.
  256. */
  257.  
  258. static int ifnetmsk(int argc, char *argv[], void *p)
  259. {
  260.     struct iface *ifp = p;
  261.     struct route *rp;
  262.  
  263.     /* Remove old entry if it exists */
  264.     
  265.     rp = rt_blookup(ifp->addr & ifp->netmask, mask2width(ifp->netmask));
  266.  
  267.     if(rp != NULLROUTE)
  268.         rt_drop(rp->target, rp->bits);
  269.  
  270.     ifp->netmask = htol(argv[1]);
  271.     rt_add(ifp->addr, mask2width(ifp->netmask), 0L, ifp, 0L, 0L, 0);
  272.     return 0;
  273. }
  274.  
  275.  
  276. /*
  277.     ifencap - Command to set interface encapsulation mode
  278. */
  279.  
  280. static int ifencap(int argc, char *argv[], void *p)
  281. {
  282.     struct iface *ifp = p;
  283.  
  284.     if (setencap(ifp, argv[1]) != 0){
  285.         tprintf("Encapsulation mode '%s' unknown\n", argv[1]);
  286.         return 1;
  287.     }
  288.     return 0;
  289. }
  290.  
  291.  
  292. /*
  293.     setencap - Function to set encapsulation mode
  294. */
  295.  
  296. int setencap(struct iface *ifp, char *mode)
  297. {
  298.     struct iftype *ift;
  299.  
  300.     for(ift = &Iftypes[0]; ift->name != NULLCHAR; ift++)
  301.         if (strnicmp(ift->name, mode, strlen(mode)) == 0)
  302.             break;
  303.     if (ift->name == NULLCHAR){
  304.         return -1;
  305.     }
  306.     
  307.     ifp->iftype = ift;
  308.     ifp->send     = ift->send;
  309.     ifp->output = ift->output;
  310.     ifp->type     = ift->type;
  311.     
  312.     return 0;
  313. }
  314.  
  315.  
  316. /* Set interface receive buffer size */
  317.  
  318. static int ifrxbuf(int argc, char *argv[], void *p)
  319. {
  320.     return 0;    /* To be written */
  321. }
  322.  
  323.  
  324. /*
  325.     ifmtu - Set interface Maximum Transmission Unit
  326. */
  327.  
  328. static int ifmtu(int argc, char *argv[], void *p)
  329. {
  330.     struct iface *ifp = p;
  331.  
  332.     ifp->mtu = atoi(argv[1]);
  333.     return 0;
  334. }
  335.  
  336.  
  337. /*
  338.     ifforw - Set interface forwarding
  339. */
  340.  
  341. static int ifforw(int argc, char *argv[], void *p)
  342. {
  343.     struct iface *ifp = p;
  344.  
  345.     ifp->forw = if_lookup(argv[1]);
  346.  
  347.     if (ifp->forw == ifp)
  348.         ifp->forw = NULLIF;
  349.     return 0;
  350. }
  351.  
  352.  
  353. /*
  354.     showiface - Display the parameters for a specified interface */
  355.  
  356. static void showiface(struct iface *ifp)
  357. {
  358.     char tmp[25];
  359.  
  360.     tprintf("%-10s IP addr %s MTU %u Link encap ", ifp->name,
  361.              inet_ntoa(ifp->addr),(int)ifp->mtu);
  362.  
  363.     if (ifp->iftype == NULLIFT) {
  364.         tprintf("not set\n");
  365.     } else {
  366.         tprintf("%s\n", ifp->iftype->name);
  367.         if (ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR)
  368.             tprintf("           Link addr %s\n",
  369.              (*ifp->iftype->format)(tmp,ifp->hwaddr));
  370.     }
  371.     
  372.     tprintf("           flags %u trace 0x%x netmask 0x%08lx broadcast %s\n",
  373.         ifp->flags,ifp->trace,ifp->netmask,inet_ntoa(ifp->broadcast));
  374.  
  375.     if (ifp->forw != NULLIF)
  376.         tprintf("           output forward to %s\n", ifp->forw->name);
  377.  
  378.     tprintf("           sent: ip %lu tot %lu idle %s\n",
  379.             ifp->ipsndcnt, ifp->rawsndcnt, tformat(secclock() - ifp->lastsent));
  380.  
  381.     tprintf("           recv: ip %lu tot %lu idle %s\n",
  382.             ifp->iprecvcnt, ifp->rawrecvcnt, tformat(secclock() - ifp->lastrecv));
  383. }
  384.  
  385.  
  386. /*
  387.     dodetach - Command to detach an interface
  388. */
  389.  
  390. int dodetach(int argc, char *argv[], void *p)
  391. {
  392.     struct iface *ifp;
  393.  
  394.     if ((ifp = if_lookup(argv[1])) == NULLIF) {
  395.         tprintf("Interface %s unknown\n", argv[1]);
  396.         return 1;
  397.     }
  398.     
  399.     if (if_detach(ifp) == -1)
  400.         tprintf("Can't detach loopback or encap interface\n");
  401.     return 0;
  402. }
  403.  
  404.  
  405. /*
  406.     if_detach - Detach a specified interface
  407. */
  408.  
  409. int if_detach(struct iface *ifp)
  410. {
  411.     int i, j;
  412.     struct iface *iftmp;
  413.     struct route *rp,*rptmp;
  414.  
  415.     if (ifp == &Loopback || ifp == &Encap)
  416.         return -1;
  417.  
  418.     /* Drop all routes that point to this interface */
  419.     
  420.     if (R_default.iface == ifp)
  421.         rt_drop(0L, 0);                                /* Drop default route */
  422.  
  423.     for (i=0; i < HASHMOD; i++) {
  424.         for (j = 0; j < 32; j++) {
  425.             for (rp = Routes[j][i]; rp != NULLROUTE; rp = rptmp) {
  426.                 
  427.                 /* Save next pointer in case we delete this entry */
  428.  
  429.                 rptmp = rp->next;
  430.                 if (rp->iface == ifp)
  431.                     rt_drop(rp->target, rp->bits);
  432.             }
  433.         }
  434.     }
  435.     
  436.     /* Unforward any other interfaces forwarding to this one */
  437.  
  438.     for (iftmp = Ifaces; iftmp != NULLIF; iftmp = iftmp->next) {
  439.         if (iftmp->forw == ifp)
  440.              iftmp->forw = NULLIF;
  441.     }
  442.  
  443.     /* Call device shutdown routine, if any */
  444.     
  445.     if (ifp->stop != NULLFP)
  446.         (*ifp->stop)(ifp);
  447.  
  448.     killproc(ifp->rxproc);
  449.     killproc(ifp->txproc);
  450.     killproc(ifp->supv);
  451.  
  452.     /* Free allocated memory associated with this interface */
  453.     
  454.     if (ifp->name != NULLCHAR)
  455.         free(ifp->name);
  456.  
  457.     if (ifp->hwaddr != NULLCHAR)
  458.         free(ifp->hwaddr);
  459.  
  460.     /* Remove from interface list */
  461.  
  462.     if (ifp == Ifaces){
  463.         Ifaces = ifp->next;
  464.     } else {
  465.  
  466.         /* Search for entry just before this one
  467.          * (necessary because list is only singly-linked.)
  468.          */
  469.  
  470.         for (iftmp = Ifaces; iftmp != NULLIF; iftmp = iftmp->next)
  471.             if(iftmp->next == ifp)
  472.                 break;
  473.         if (iftmp != NULLIF && iftmp->next == ifp)
  474.             iftmp->next = ifp->next;
  475.     }
  476.     
  477.     /* Finally free the structure itself */
  478.  
  479.     free((char *)ifp);
  480.     return 0;
  481. }
  482.  
  483.  
  484. /*
  485.     if_lookup - Given the ascii name of an interface, return a pointer to the
  486.                     structure, or NULLIF if it doesn't exist
  487. */
  488.  
  489. struct iface *if_lookup(char *name)
  490. {
  491.     struct iface *ifp;
  492.  
  493.     for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  494.         if (strcmp(ifp->name, name) == 0)
  495.             break;
  496.  
  497.     return ifp;
  498. }
  499.  
  500.  
  501. /*
  502.     ismyaddr - Return iface pointer if 'addr' belongs to one of our interfaces,
  503.                   NULLIF otherwise. This is used to tell if an incoming IP
  504.                    datagram is for us, or if it has to be routed.
  505. */
  506.  
  507. struct iface *ismyaddr(int32 addr)
  508. {
  509.     struct iface *ifp;
  510.  
  511.     for (ifp = Ifaces; ifp != NULLIF; ifp = ifp->next)
  512.         if(addr == ifp->addr)
  513.             break;
  514.     return ifp;
  515. }
  516.  
  517.  
  518. /*
  519.     mask2width - Given a network mask, return the number of contiguous
  520.                      1-bits starting from the most significant bit.
  521. */
  522.  
  523. static int mask2width(int32 mask)
  524. {
  525.     int width,i;
  526.     width = 0;
  527.  
  528.     for(i = 31; i >= 0; i--) {
  529.         if(!(mask & (1L << i)))
  530.             break;
  531.         width++;
  532.     }
  533.     
  534.     return width;
  535. }
  536.  
  537.  
  538. /*
  539.     if_name - return buffer with name + comment
  540. */
  541.  
  542. char *if_name(struct iface *ifp, char *comment)
  543. {
  544.     char *result = mallocw(strlen(ifp->name) + strlen(comment) + 1 );
  545.     strcpy(result, ifp->name );
  546.     return strcat(result, comment);
  547. }
  548.  
  549.  
  550. /* Raw output routine that tosses all packets. Used by dialer, tip, etc */
  551.  
  552. int bitbucket(struct iface *ifp, struct mbuf *bp)
  553. {
  554.     free_p(bp);
  555.     return 0;
  556. }
  557.